package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.domain.IotMsgNotifyData;
import com.zzyl.nursing.domain.IotMsgService;
import com.zzyl.nursing.service.IDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.service.IDeviceDataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 设备上报数据表Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-06-09
 */
@Service
public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceData> implements IDeviceDataService
{
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private IDeviceService deviceService;

    /**
     * 查询设备上报数据表
     * 
     * @param id 设备上报数据表主键
     * @return 设备上报数据表
     */
    @Override
    public DeviceData selectDeviceDataById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询设备上报数据表列表
     * 
     * @param deviceData 设备上报数据表
     * @return 设备上报数据表
     */
    @Override
    public List<DeviceData> selectDeviceDataList(DeviceData deviceData)
    {
        return deviceDataMapper.selectDeviceDataList(deviceData);
    }

    /**
     * 新增设备上报数据表
     * 
     * @param deviceData 设备上报数据表
     * @return 结果
     */
    @Override
    public int insertDeviceData(DeviceData deviceData)
    {
        return save(deviceData) ? 1 : 0;
    }

    /**
     * 修改设备上报数据表
     * 
     * @param deviceData 设备上报数据表
     * @return 结果
     */
    @Override
    public int updateDeviceData(DeviceData deviceData)
    {
        return updateById(deviceData) ? 1 : 0;
    }

    /**
     * 批量删除设备上报数据表
     * 
     * @param ids 需要删除的设备上报数据表主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除设备上报数据表信息
     * 
     * @param id 设备上报数据表主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 保存设备上报数据
     * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveDeviceData(String contentStr) {
        // 将JSON类型的字符串转换成JSONObject对象
        JSONObject jsonObject = JSONUtil.parseObj(contentStr);
        // 从JSONObject对象中获取notify_data字段
        Object object = jsonObject.get("notify_data");
        //  将object对象数据封装成IotMsgNotifyData对象
        IotMsgNotifyData iotMsgNotifyData = BeanUtil.toBean(object, IotMsgNotifyData.class);

        //  判断报文转换是否成功
        if(ObjectUtil.isEmpty(iotMsgNotifyData)){
            throw new BaseException("报文转换失败");
        }

        //  判断设备是否存在
        Device device = deviceService.getOne(new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotMsgNotifyData.getHeader().getDeviceId()));
        if (ObjectUtil.isEmpty(device)){
            throw new BaseException("设备不存在");
        }

        //  在设备数据表中，一次上报需要保存一个设备的多个物模型数据。比如，烟雾报警有三个物模型，那么当接收到一个数据上报的时候，就要保存三条数据到设备数据中
        List<DeviceData> deviceDataList = new ArrayList<>();

        //从报文中获取物模型数据
        IotMsgService iotMsgService = iotMsgNotifyData.getBody().getServices().get(0);

        //从模型数据中获取时间，将时间转化为想要的时间格式
        //处理上报时间日期
        LocalDateTime eventTime = LocalDateTimeUtil.parse(iotMsgService.getEventTime(), "yyyyMMdd'T'HHmmss'Z'");
        //日期时区转换
        LocalDateTime alarmTime = eventTime.atZone(ZoneId.from(ZoneOffset.UTC))
                .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                .toLocalDateTime();
        Map<String, Object> properties = iotMsgService.getProperties();
        Set<Map.Entry<String, Object>> entries = properties.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            DeviceData deviceData = new DeviceData();
            BeanUtil.copyProperties(device, deviceData, "id");
            deviceData.setAlarmTime(alarmTime);
            deviceData.setFunctionId(entry.getKey());
            deviceData.setDataValue(String.valueOf(entry.getValue()));
            deviceDataList.add(deviceData);
        }
        // 将数据批量保存到数据库中
        saveBatch(deviceDataList);
    }
}
